1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright  1999-2004 The Apache Software Foundation.
7    *
8    *  Licensed under the Apache License, Version 2.0 (the "License");
9    *  you may not use this file except in compliance with the License.
10   *  You may obtain a copy of the License at
11   *
12   *      http://www.apache.org/licenses/LICENSE-2.0
13   *
14   *  Unless required by applicable law or agreed to in writing, software
15   *  distributed under the License is distributed on an "AS IS" BASIS,
16   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   *  See the License for the specific language governing permissions and
18   *  limitations under the License.
19   *
20   */
21  package com.sun.org.apache.xml.internal.security.transforms.params;
22  
23  
24  
25  import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
26  import com.sun.org.apache.xml.internal.security.transforms.TransformParam;
27  import com.sun.org.apache.xml.internal.security.utils.ElementProxy;
28  import com.sun.org.apache.xml.internal.security.utils.HelperNodeList;
29  import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
30  import org.w3c.dom.Document;
31  import org.w3c.dom.Element;
32  import org.w3c.dom.Node;
33  import org.w3c.dom.NodeList;
34  
35  
36  /**
37   * Implements the parameters for the <A
38   * HREF="http://www.w3.org/TR/xmldsig-filter2/">XPath Filter v2.0</A>.
39   *
40   * @author $Author: mullan $
41   * @see <A HREF="http://www.w3.org/TR/xmldsig-filter2/">XPath Filter v2.0 (TR)</A>
42   * @see <A HREF="http://www.w3.org/Signature/Drafts/xmldsig-xfilter2/">XPath Filter v2.0 (editors copy)</A>
43   */
44  public class XPath2FilterContainer extends ElementProxy
45          implements TransformParam {
46  
47     /** Field _ATT_FILTER */
48     private static final String _ATT_FILTER = "Filter";
49  
50     /** Field _ATT_FILTER_VALUE_INTERSECT */
51     private static final String _ATT_FILTER_VALUE_INTERSECT = "intersect";
52  
53     /** Field _ATT_FILTER_VALUE_SUBTRACT */
54     private static final String _ATT_FILTER_VALUE_SUBTRACT = "subtract";
55  
56     /** Field _ATT_FILTER_VALUE_UNION */
57     private static final String _ATT_FILTER_VALUE_UNION = "union";
58  
59     /** Field INTERSECT */
60     public static final String INTERSECT =
61        XPath2FilterContainer._ATT_FILTER_VALUE_INTERSECT;
62  
63     /** Field SUBTRACT */
64     public static final String SUBTRACT =
65        XPath2FilterContainer._ATT_FILTER_VALUE_SUBTRACT;
66  
67     /** Field UNION */
68     public static final String UNION =
69        XPath2FilterContainer._ATT_FILTER_VALUE_UNION;
70  
71     /** Field _TAG_XPATH2 */
72     public static final String _TAG_XPATH2 = "XPath";
73  
74     /** Field XPathFiler2NS */
75     public static final String XPathFilter2NS =
76        "http://www.w3.org/2002/06/xmldsig-filter2";
77  
78     /**
79      * Constructor XPath2FilterContainer
80      *
81      */
82     private XPath2FilterContainer() {
83  
84        // no instantiation
85     }
86  
87     /**
88      * Constructor XPath2FilterContainer
89      *
90      * @param doc
91      * @param xpath2filter
92      * @param filterType
93      */
94     private XPath2FilterContainer(Document doc, String xpath2filter,
95                                   String filterType) {
96  
97        super(doc);
98  
99        this._constructionElement
100          .setAttributeNS(null, XPath2FilterContainer._ATT_FILTER, filterType);
101       this._constructionElement.appendChild(doc.createTextNode(xpath2filter));
102    }
103 
104    /**
105     * Constructor XPath2FilterContainer
106     *
107     * @param element
108     * @param BaseURI
109     * @throws XMLSecurityException
110     */
111    private XPath2FilterContainer(Element element, String BaseURI)
112            throws XMLSecurityException {
113 
114       super(element, BaseURI);
115 
116       String filterStr = this._constructionElement.getAttributeNS(null,
117                             XPath2FilterContainer._ATT_FILTER);
118 
119       if (!filterStr
120               .equals(XPath2FilterContainer
121               ._ATT_FILTER_VALUE_INTERSECT) &&!filterStr
122                  .equals(XPath2FilterContainer
123                  ._ATT_FILTER_VALUE_SUBTRACT) &&!filterStr
124                     .equals(XPath2FilterContainer._ATT_FILTER_VALUE_UNION)) {
125          Object exArgs[] = { XPath2FilterContainer._ATT_FILTER, filterStr,
126                              XPath2FilterContainer._ATT_FILTER_VALUE_INTERSECT
127                              + ", "
128                              + XPath2FilterContainer._ATT_FILTER_VALUE_SUBTRACT
129                              + " or "
130                              + XPath2FilterContainer._ATT_FILTER_VALUE_UNION };
131 
132          throw new XMLSecurityException("attributeValueIllegal", exArgs);
133       }
134    }
135 
136    /**
137     * Creates a new XPath2FilterContainer with the filter type "intersect".
138     *
139     * @param doc
140     * @param xpath2filter
141     * @return the filter.
142     */
143    public static XPath2FilterContainer newInstanceIntersect(Document doc,
144            String xpath2filter) {
145 
146       return new XPath2FilterContainer(doc, xpath2filter,
147                                        XPath2FilterContainer
148                                           ._ATT_FILTER_VALUE_INTERSECT);
149    }
150 
151    /**
152     * Creates a new XPath2FilterContainer with the filter type "subtract".
153     *
154     * @param doc
155     * @param xpath2filter
156     * @return the filter.
157     */
158    public static XPath2FilterContainer newInstanceSubtract(Document doc,
159            String xpath2filter) {
160 
161       return new XPath2FilterContainer(doc, xpath2filter,
162                                        XPath2FilterContainer
163                                           ._ATT_FILTER_VALUE_SUBTRACT);
164    }
165 
166    /**
167     * Creates a new XPath2FilterContainer with the filter type "union".
168     *
169     * @param doc
170     * @param xpath2filter
171     * @return the filter
172     */
173    public static XPath2FilterContainer newInstanceUnion(Document doc,
174            String xpath2filter) {
175 
176       return new XPath2FilterContainer(doc, xpath2filter,
177                                        XPath2FilterContainer
178                                           ._ATT_FILTER_VALUE_UNION);
179    }
180 
181    /**
182     * Method newInstances
183     *
184     * @param doc
185     * @param params
186     * @return the nodelist with the data
187     */
188    public static NodeList newInstances(Document doc, String[][] params) {
189 
190       HelperNodeList nl = new HelperNodeList();
191 
192       XMLUtils.addReturnToElement(doc, nl);
193 
194       for (int i = 0; i < params.length; i++) {
195          String type = params[i][0];
196          String xpath = params[i][1];
197 
198          if (!(type.equals(XPath2FilterContainer
199                  ._ATT_FILTER_VALUE_INTERSECT) || type
200                     .equals(XPath2FilterContainer
201                     ._ATT_FILTER_VALUE_SUBTRACT) || type
202                        .equals(XPath2FilterContainer
203                           ._ATT_FILTER_VALUE_UNION))) {
204             throw new IllegalArgumentException("The type(" + i + ")=\"" + type
205                                                + "\" is illegal");
206          }
207 
208          XPath2FilterContainer c = new XPath2FilterContainer(doc, xpath, type);
209 
210          nl.appendChild(c.getElement());
211          XMLUtils.addReturnToElement(doc, nl);
212       }
213 
214       return nl;
215    }
216 
217    /**
218     * Creates a XPath2FilterContainer from an existing Element; needed for verification.
219     *
220     * @param element
221     * @param BaseURI
222     * @return the filter
223     *
224     * @throws XMLSecurityException
225     */
226    public static XPath2FilterContainer newInstance(
227            Element element, String BaseURI) throws XMLSecurityException {
228       return new XPath2FilterContainer(element, BaseURI);
229    }
230 
231    /**
232     * Returns <code>true</code> if the <code>Filter</code> attribute has value "intersect".
233     *
234     * @return <code>true</code> if the <code>Filter</code> attribute has value "intersect".
235     */
236    public boolean isIntersect() {
237 
238       return this._constructionElement
239          .getAttributeNS(null, XPath2FilterContainer._ATT_FILTER)
240          .equals(XPath2FilterContainer._ATT_FILTER_VALUE_INTERSECT);
241    }
242 
243    /**
244     * Returns <code>true</code> if the <code>Filter</code> attribute has value "subtract".
245     *
246     * @return <code>true</code> if the <code>Filter</code> attribute has value "subtract".
247     */
248    public boolean isSubtract() {
249 
250       return this._constructionElement
251          .getAttributeNS(null, XPath2FilterContainer._ATT_FILTER)
252          .equals(XPath2FilterContainer._ATT_FILTER_VALUE_SUBTRACT);
253    }
254 
255    /**
256     * Returns <code>true</code> if the <code>Filter</code> attribute has value "union".
257     *
258     * @return <code>true</code> if the <code>Filter</code> attribute has value "union".
259     */
260    public boolean isUnion() {
261 
262       return this._constructionElement
263          .getAttributeNS(null, XPath2FilterContainer._ATT_FILTER)
264          .equals(XPath2FilterContainer._ATT_FILTER_VALUE_UNION);
265    }
266 
267    /**
268     * Returns the XPath 2 Filter String
269     *
270     * @return the XPath 2 Filter String
271     */
272    public String getXPathFilterStr() {
273       return this.getTextFromTextChild();
274    }
275 
276    /**
277     * Returns the first Text node which contains information from the XPath 2
278     * Filter String. We must use this stupid hook to enable the here() function
279     * to work.
280     *
281     * $todo$ I dunno whether this crashes: <XPath> here()<!-- comment -->/ds:Signature[1]</XPath>
282     * @return the first Text node which contains information from the XPath 2 Filter String
283     */
284    public Node getXPathFilterTextNode() {
285 
286       NodeList children = this._constructionElement.getChildNodes();
287       int length = children.getLength();
288 
289       for (int i = 0; i < length; i++) {
290          if (children.item(i).getNodeType() == Node.TEXT_NODE) {
291             return children.item(i);
292          }
293       }
294 
295       return null;
296    }
297 
298    /**
299     * Method getBaseLocalName
300     *
301     * @return the XPATH2 tag
302     */
303    public final String getBaseLocalName() {
304       return XPath2FilterContainer._TAG_XPATH2;
305    }
306 
307    /**
308     * Method getBaseNamespace
309     *
310     * @return XPATH2 tag namespace
311     */
312    public final String getBaseNamespace() {
313       return XPath2FilterContainer.XPathFilter2NS;
314    }
315 }